I've decided to donate this utility to the budding geniuses of the GS
programming world - or anyone who's faced with the daunting prospect of
having to convert 8088 IBM assembly language source into 65816 code.

There's a lot of tedious and confusing work to be done. This will take
off SOME of the load...

This works on a single 8088 line at a time: there's no look-ahead;
look-back; or any attempt WHATSOEVER to figure out what's happening:
it just translates the code...

IT WILL NOT   NOT    NOT  produce a finished product for you! You'll
still have work to do, but it WILL probably reduce your work by 50%.

It is worth what you paid for it. You'll get the same level of support
from me : ZERO. (Sorry, but I haven't got the time to help you convert
code...you got this for free, and that's all your gonna get...)


FIRST: HOW GOOD IS THE TRANSLATION?
Well, in a random sample of 36 instructions (see the sample file) from the
8088, the number of cycles required was 429. The conversion, after deleting
unneeded lines, took 196 cycles. Thus, even allowing for different CPU
speeds, the translation will be, in fact, slightly FASTER than the
original code.

FILES:
The converted files have the same root name as your original file(s),
along with ".ORCA" appended. Unless you specified otherwise, a line limit
of 800 lines per file was imposed (to previent the file(s) from becomming
too large for your editor). In this case, and additional appendage is
added: ".n", where "n" is a number beginning at 1. Thus, if your original
file was named "MYSTUFF", and at 800 lines per file, it required 4 files,
then these files are:
   mystuff.orca
   mystuff.orca.1
   mystuff.orca.2
   mystuff.orca.3

BASIC FILE STRUCTURE

The original IBM line is retained in the file, preceeded by an "!",
which effectively comments out the line. This is so that you can review the
line conversion  which follows. Additionally, the original line may be
followed by a warning notice. These notices, described below, are placed
in the file when an unusual circumstance is encountered. THE ABSENCE OF
A WARNING LINE DOES NOT RELIEVE YOU OF VERIFYING THE CONVERSION! These
warnings are merely a convenience for you.

WARNINGS

      notWarning = '! Warning : requires NOT: eor #$FFFF';
      negWarning = '! Warning : requires NEG: eor #$FFFF; adc #1';
These warnings usually occur when an operand contains NOT or NEG. The
conversion handles these instructions if they appear in the instruction
field of the original source, such as
         label  NOT op  (the conversion IS done)
but      label  XOR BX, NOT something
will produce the warning, because the conversion was not done on the operand.


      regWarning = '! Warning : May lose register data here!';
This warning appears (perhaps too frequently) in many circumstances, usually
when a line has been converted that uses one of the 65816 registers in
an abritrary fashion. It does NOT mean that you WILL lose a register's
data, only that you should look above and verify that the register used is
in fact, clear for use. EQUALLY, the absence of this warning does not mean
everything's perfect. It's YOUR responsibility to verify continuity. However,
in cases where it seemed necessary. a "PHA"/"PLA"  or "SAVE/RESTORE"
was inserted. Converse to the above, you may find that these are not
necessary, and may be deleted.

      macWarning = '! Warning : Macro follows!';
This is inserted when an Orca/APW macro was used in translating. Please
verify that the parameters to the macro are correct.

      loopWarning ='! Warning : Loop Encountered! (try Move macro?)';
We have tried to recognize and duplicate loop conditions. This is extremely
difficult in a line-by-line conversion of 8088 code since that code
frequently uses a register to control the loop, initialized any number
of lines above. There is NO guarantee, therefore, that all loops have
been caught! Thus there is no guarantee that this warning has been inserted
in every location it should have been. On the other hand, you'll notice
that we've done a pretty good job of inserting our own labels and
branches...

      HandledWarning ='! Warning : line above was NOT CONVERTED';
(This should be obvious...)

      shiftWarning = '!Warning : special shift instruction detected';
As you know the 8088 contains three shift instructions which maintain the
high or low bit, and are not found on the 65816 (SAR,ROL, & ROR).
Like the NOT/NEG above, we have handled these if they appear as an
instruction, but not if they appear in the operand field. Check for loss
of register data.

REGISTERS

 IBM registers:
      A, B, C, & D are general purpose
      SI & DI          string indexes
      SP & BP          stack
      CS,DS,SS,ES      64k (or less) Segment regs as
            CS = program instructions
            DS = data & source strings
            SS = stack (using BP as base register)
            ES = (extra seg): destination strings

The basic rule here is that the Accumulator (A) is maintained; the X & Y
registers are used exclusively for indexing operations (see below) and
all other 8088 registers are maintained in Zero Page. The decision here was
on how to use the high/low attributes of these registers. In the case of the
A reg, the generated code uses the "short M" macro followed by any needed
"pha/xba/pla" when the H attribute was used.

In the case of all the other registers, now in zero page, the following
convention was used:
   BL equ 0
   BH equ 0
   BX equ 0  (because the code generates BH+1
   CL equ 4
   CH equ 4
   CX equ 4   etc
That is, all register specifications (ie BL,BH,BX) point to the SAME 2*WORD!
We use 2 words since that is needed for long addressing. As you know,
the 8088 registers are in High/Low order, (thus $FF11 is FF/11) while the
addressing mode of the 816 requires Low/High order ($FF11 is 11/FF). Since
we are using psuedo registers for all but the Accumulator (which perversly
is High/Low) a reference to BH is 1 byte past BL.

Therefore a reference to BL (with short M) will access properly, as will
a longM reference to BX. The reference to BH becomes "short M" BH+1, which
will now also be correct. Remember to leave four bytes for those registers
which are used for long addressing.

The 816, on a LDA will load the word, which is L/H, as H/L. In this form
the register order is the same as the 8088. Doing a "short M" (SEP #$20)
and a STA will then store the low byte at BL, or the beginning of the word.
To now do a MOV AH, the code will do an XBA, STA BH+1, which puts the
8-bit accumulator into BL+1, or the high byte. (Note that the
actual translation however, will be "sta  BH+1", which is correct, since
we have defined BL,BH, & BX to be the same address...)

You will want to remain aware of this register-order difference as you
proceed with your hand-conversion.

Also, you'll want to remember the distinction between registers and
labels when used in indirect addressing. The form: [BX + 5] will
take the CONTENTS of BX, add 5 to it, and then use that result as the
address from which to retrieve data. On the other hand, the form
[label + 5] will take the ADDRESS (or EQUATE) of label, and add 5 to
it. Thus in the former case, the conversion will have to be
   lda bx
   clc
   adc #$5
   tay
whereas in the latter case, it is simply
   ldy #label+5
      

Note: we have tried to track the state of the accumulator (short or long)
as best as possible, but it may be that the index size is incorrect in
some few circumstances. Please verify.

CS, DS, ES, SS registers are also zero page words. in the case of indirect
addressing , these are treated as base addresses. In appropriate cases,
they have been left with the required following colon (ie ES:). In Orca/APW
the use of bank pointers can be obviated by using the "USES DATA"
directive. Long addressing is assumed.

Creation of the register equates is up to you.

STRUCTURES

One feature of 8088 assembly which is absent from the 65816 Orca/APW is
the use of structures. As you know, this is also the single largest headache
in convertion. Addressing can vary from the simple to the complex:

  mov ax,label
  mov ax,lab.field
  mov ax lab[xx]
  mov ax,[si].field
  mov ax,rec.field[xx]
  mov ax,[si].field[xx]

In order to solve this thorny problem, the following key was adopted:

 THE KEY!!!!
      is that structure's fields MUST be defined as OFFSETS into
      the structure : ie
      ddd struct
      a  db 0
      b dw 27
      c dc 'h'
      endstruct      BECOMES

     DDD ds 4
     a equ 0
     b equ 1
     c equ 3

Again: a struct becomes simple storage equal to the size of the structure;
the fields in the struct become offset EQUates. THIS CONVERSION MUST BE
DONE BY YOU: data conversion is not included in our service.

Assuming this format, the conversion yeilds the following:

  form = mov ax,label
      becomes LDA label

  form = mov ax,lab.field
      becomes LDA lab+field

  form = mov ax lab[xx]
      becomes LDX #XX
              LDA LAB,X

  form = mov ax,[si].field
      becomes LDY #field
              LDA [si],Y

  form = mov ax,rec.field[xx]
      becomes LDX #field+xx
              LDA rec,x

  form = mov ax,[si].field[xx]
      becomes LDY #field+xx
              LDA [SI],Y

Notice that records are indexed via the X register (absolute indexed,X)
and indirect records are address using Y (DP indirect long indexed,Y)



INSTRUCTIONS NOT CONVERTED

String comparisons are left to you: CMPS SCAS XLAT.
Parity checks: JNP JPO JP JPE
Ascii & Decimal adjusts: AAA AAD AAM AAS DAA DAS
Misc: ESC INT INTO LOCK CLD STD NMI SINGLESTEP


WATCH FORs

Operations performed on two registers:
   due to the way conversions are performed, you need to watch for
   operations performed on two registers where the second operand
   is the accumulator. You'll need to delete a line:
   XOR DX,AX
   will appear as:
         pha
         lda DX
         eor AX
         sta DX
         pla
   this should be
         pha  (optional: leave in if necessary)
         eor DX
         sta DX
         pla

Shifts of the accumulator may appear as
      asl #1
      convert this to
      asl a
      You may want to replace some shifts with a macro such as
            ASL2 MASL MLSR etc

ORs  8088 frequently uses "OR reg,reg" to check for zero.
   this can be replaced with a simple beq if a "LDA" preceeded it.

MOV reg1,[reg2] may show an incorrect translation. It should be
   LDA [reg2]
   STA reg1

MUL reg is 'Multiply reg by Accumulator'. It is translated as
   MUL reg
   Consider using the MUL macro.
   
PROC/ENDPROC: these are NOT translated. Repalce these with START/END.

RET: is translated as "RTS". It may need to be "RTL".

PUSH & POP: these are translated into Macros as Ph2 and Pl2. This is
appropriate for all registers except the GS's A,X, & Y. Remember to
switch to pha, phx etc as needed. Also, if DI, SI, BX etc are pushed
and they contain a long address, then switch the macro to Ph4/Pl4.


HOLDXY: in complex indirect addressing  the (eventual) X/Y register value
may require computation to determine the value. Since calculations must
be done in the accumulator, the result is stored in a word named "HOLDXY".
(You must define this location yourself.) In many cases however, you will
be able to replace this with a simple TAX or TAY.

CONVENTIONS:
 IBM instruction are translated into UPPERCASE: (MOV)
 APW/Orca macros are Capitalized: (Move)
 65816 instructions are in lowercase: (lda)

METHODOLOGY AND HINTS FOR CONVERSION

Instructions which are of the form
   MOV DI,LABEL
are translated as
   lda label
   sta DI
You may prefer, depending on context, to convert them to
   ldx label
   stx DI
since the X register is used only for indexing.

Since the parser cannot distinguish between a label and an equate,
instructions such as:
   MOVE DI,LABEL1*256 + LABEL2/4
are treated as equates. If the LABEL is a label then you'll have to
perform the operation yourself.
   lda label1
   masl 8
   sta temp
   lda label2
   mlsr 2
   clc
   adc temp   
You'll have to track the distinction between labels and equates yourself,
in order to decide to use "#" or not.

You may wish to also include an AX/AH/AL zero page equivalent (as are
B, C, D etc) for saving the accumulator.

As a general procedure, we recommend the following: go thru the converted
source in three passes. The first pass should simply be a read-thru, in
order to familiarize yourself with the translation. Having both the original
lines and the conversions, you'll be able to understand the logic flow
quite readily. You can insert notes in the code here on many things which
will be obvious to you, and which you'll want to change later. If you've
got the time (& the paper), we suggest printing out this first version
you have recieved from us. We STRONGLY suggest that you DO NOT work on
the original translated version, but only on a backup!

During the second pass, remove any unwanted lines,
such as "EXTERN" and follow the flow of the code. You may want to make
simple hand changes here and remove the warnings for those changes. 
Equally, you may want to insert your own warning notes on tricky sections:
a keyboard macro would be handy. Do NOT remove the original 8088 source
lines! On the third pass, use the 8088 source lines to carefully follow
the original programmer's intent and check for registers being stepped on
and so on. We strongly suggest that you leave the original (commented out)
8088 lines in until you have successfully assembled and debugged your
application.

Also, remember to check out the included examples file, which includes
samples of code produced by our translator, and the final translation
of that sample.

What it asks for:
File to convert: (name the original file)
Keep the old lines? : (you should so you can check the conversion)
Keep the file? : (Yeah, if you want to edit it; no if you just want to
                  watch things flash by on the screen...)
Max # of lines in each out_file: (800 ish) (a 4000 line IBM file could generate
                  as many as 25000 lines of converted code. This option
                  lets you split up the conversion into several files -
                  done automatically- of approximately n (ie 800 ish) lines.)
enter 3 chars for labels: if you enter ABC then the labels in the file(s)
            will be ABC1, ABC2, ABC3 etc
use PHA/PLA?: if you say Y here, you get an awful lot of converted lines
         beginning with PHA and ending with PLA. It was intended as a
         safety measure, but it got carried away. Assuming you know what
         you're doing, you should probably select "n" here.
         
I STRONGLY SUGGEST that you try a simple sample of your IBM code FIRST, so
that you can see what actually happens...

I have also included CONVERT.DATA, which will do a conversion of SOME
but not all 8088 data structures. The 8088 code MUST all be data (no opcodes)
for this to work. (You'll have to separate it out yourself...)



A FINAL WORD
The conversion you have received has successfully converted nearly 90%
of the standard 8088 assembly language instructions. It has NOT produced
source you can simply assemble for the GS. You will still have to verify
the logic, remove unneeded lines, handle untranslated (or untranslatable)
instructions, convert data structures and verify that registers are not
stepped on by succeeding instructions.

On the other hand, assuming that you're more familiar with the GS than
the 8088, you'll find that these remaining tasks (which you have to do
regardless) will now be much easier than starting from cold.
 
We make no warantee, express or implied, as to the fitness or suitability
of the service rendered by us, for and to your application and needs. You,
as the original contractee, are ultimately and solely responsible for the
resulting software product. Since our conversion service provides, and is
acknowledged by you to provide, only a partial conversion of 8088 source
code, and since it is also acknowledged by you that such being the case,
you bear the additional responsibility of finishing and verifying the
final source code, then UNDER NO CIRCUMSTANCES WHATSOEVER, will we be
liable or responsible for incidental, consequential or direct loss or
damage caused or alleged to be caused directly or indirectly by this
conversion, including (but not limited to) loss of business, data,
or anticipated profit. Our sole responsibility has been to use our
copyrighted and proprietary software to partially convert the source, as
supplied by you, from 8088 to 65816 assembly language source. No other
service or warantee is expressed or implied.

(Whew!)

GENIE: T.VALLEAU
